package com.jdk.learn.juc._07Conditon;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by ricky
 * on 2018/2/1.
 *
  Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用
 法上与使用 Object.wait 访问的隐式监视器类似，但提供了更强大的
 功能。需要特别指出的是，单个 Lock 可能与多个 Condition 对象关
 联。为了避免兼容性问题，Condition 方法的名称与对应的 Object 版
 本中的不同。
  在 Condition 对象中，与 wait、notify 和 notifyAll 方法对应的分别是
 await、signal 和 signalAll。
  Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得
 Condition 实例，请使用其 newCondition() 方法。



 本示例实现线程交替执行

  编写一个程序，开启 3 个线程，这三个线程的 ID 分别为
 A、B、C，每个线程将自己的 ID 在屏幕上打印 10 遍，要
 求输出的结果必须按顺序显示。
 如：ABCABCABC…… 依次递归

 */
public class _07ConditonDemo {
    public static void main(String[] args) {
        Loops loops=new Loops();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                loops.A();
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                loops.B();
            }
        },"B").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                loops.C();
            }
        },"C").start();
    }

}

class Loops {
    private int threadNum=1;//A线程  2是B线程 3是C线程

    private Lock lock=new ReentrantLock();

    private Condition conditionA=lock.newCondition();
    private Condition conditionB=lock.newCondition();
    private Condition conditionC=lock.newCondition();


    /**
     * 循环A
     */
    public void A(){
        lock.lock();
        try {
            if (threadNum!=1) {//不是A线程
                conditionA.await();
            }
            System.out.println("---------------------------------");
            System.out.println(Thread.currentThread().getName()+"\t "+"-----------------");
            //变更为B
            threadNum=2;
            conditionB.signal();//唤醒B
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 循环B
     */
    public void B(){
        lock.lock();
        try {
            if (threadNum!=2) {//不是B线程
                conditionB.await();
            }
            System.out.println(Thread.currentThread().getName()+"\t "+"-----------------");
            //变更为C
            threadNum=3;
            conditionC.signal();//唤醒C
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 循环C
     */
    public void C(){
        lock.lock();
        try {
            if (threadNum!=3) {//不是C线程
                conditionC.await();
            }
            System.out.println(Thread.currentThread().getName()+"\t "+"-----------------");
            //变更为A
            threadNum=1;
            conditionA.signal();//唤醒A
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}
